 1.Zookeeper-开源客户端
   
   ZkClient
   ZkClient是Github上一个开源的zookeeper客户端，在Zookeeper原生API接口之上进行了包装，是一个
更易用的Zookeeper客户端，同时，zkClient在内部还实现了了诸如Session超时重连、Watcher反复注册
等功能
   接下来，还是从创建会话、创建节点、读取数据、更更新数据、删除节点等⽅方⾯面来介绍如何使⽤用zkClient
这个zookeeper客户端
   添加依赖：
   在pom.xml文件中添加如下内容
   <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.14</version>
    </dependency>
    <dependency>
        <groupId>com.101tec</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.2</version>
    </dependency>
	1).创建会话
    使用ZkClient可以轻松的创建会话，连接到服务端。　
package com.lagou.zk.demo;

import org.I0Itec.zkclient.ZkClient;

public class ZKDemo {
    public static void main(String[] args) {
        //先获取到zkclient对象,client与zk集群通信端口是2181
        final ZkClient zkClient = new ZkClient("linux121:2181");//创建了ZK集群的会话
        System.out.printf("zkclient is ready");
    }
}

	运行结果：zkclient is ready
    结果表明已经成功创建会话。
	2).创建节点
    ZkClient提供了递归创建节点的接口，即其帮助开发者先完成⽗父节点的创建，再创建子节点
package com.lagou.zk.demo;

import org.I0Itec.zkclient.ZkClient;

public class ZKDemo {
    public static void main(String[] args) {
        //先获取到zkclient对象,client与zk集群通信端口是2181
        final ZkClient zkClient = new ZkClient("linux121:2181");//创建了ZK集群的会话
        System.out.println("zkclient is ready");
        //1 创建节点
        zkClient.createPersistent("/lg-client/lg-c1", true);
        System.out.println("path is created");
    }
}

	运行结果：zkclient is ready
              path is created
    结果表明已经成功创建了节点，值得注意的是，ZkClient通过设置createParents参数为true可以递归的
先创建父节点，再创建子节点
    3).删除节点
    ZkClient提供了递归删除节点的接口，即其帮助开发者先删除所有子节点（存在），再删除父节点。
package com.lagou.zk.demo;

import org.I0Itec.zkclient.ZkClient;

public class ZKDemo {
    public static void main(String[] args) {
        //先获取到zkclient对象,client与zk集群通信端口是2181
        final ZkClient zkClient = new ZkClient("linux121:2181");//创建了ZK集群的会话
        System.out.println("zkclient is ready");
        //1 创建节点
        zkClient.createPersistent("/lg-client/lg-c1", true);//如果级联创建，第二个参数设置为true
        System.out.println("path is created");
        //2 删除节点
        //zkClient.delete("/lg-client");
        zkClient.deleteRecursive("/lg-client");//递归删除可以删除非空节点，先删除子节点，然后删除父节点
        System.out.println("delete path is success");
    }
}

	运行结果: zkclient is ready
               path is created
               delete path is success
    结果表明ZkClient可直接删除带⼦子节点的父节点，因为其底层先删除其所有子节点，然后再删除父节点
	4).监听节点变化
package com.lagou.zk.demo;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.ZkClient;

import java.util.List;

/*
演示zkclient如何使用监听器
 */
public class Get_Child_Change {
    public static void main(String[] args) throws InterruptedException {
        //获取到zkClient
        final ZkClient zkClient = new ZkClient("linux121:2181");
        //zkClient对指定目录监听(不存在目录:/lg-client)，指定收到通知之后的逻辑
        //对/lg-client注册了监听器
        zkClient.subscribeChildChanges("/lg-client", new IZkChildListener() {
            //该方法是接收到通知之后的执行逻辑定义
            public void handleChildChange(String path, List<String> childs) throws Exception {
                // 打印节点信息
                System.out.println(path + " childs changes ,current childs "+ childs);
            }
        });
        //使用zkClient创建节点，删除节点，验证监听器是否运行
        zkClient.createPersistent("/lg-client");
        Thread.sleep(1000);//只是为了方便观察结果数据
        zkClient.createPersistent("/lg-client/c1");
        Thread.sleep(1000);
        zkClient.delete("/lg-client/c1");
        Thread.sleep(1000);

        zkClient.delete("/lg-client");

        Thread.sleep(Integer.MAX_VALUE);
        
        /*
        1 监听器器可以对不不存在的⽬目录进⾏行行监听
        2 监听⽬目录下⼦子节点发⽣生改变，可以接收到通知，携带数据有⼦子节点列列表
        3 监听⽬目录创建和删除本身也会被监听到
        */
    }
}

	运行结果：/lg-client childs changes ,current childs []
              /lg-client childs changes ,current childs [c1]
              /lg-client childs changes ,current childs []
              /lg-client childs changes ,current childs null
	结果表明：
    客户端可以对一个不存在的节点进行子节点变更的监听。
    一旦客户端对一个节点注册了子节点列表变更监听之后，那么当该节点的子节点列表发生变更时，服务
端都会通知客户端，并将最新的子节点列列表发送给客户端
　  该节点本身的创建或删除也会通知到客户端。
    5).获取数据(节点是否存在、更新、删除)
package com.lagou.zk.demo;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;

//使用监听器监听节点数据的变化
public class Get_Data_Change {
    public static void main(String[] args) throws InterruptedException {
        //获取zkClient对象
        final ZkClient zkClient = new ZkClient("linux121:2181");
        //设置自定义序列化类型,否则会报错
        zkClient.setZkSerializer(new ZkStrSerializer());
        //判断节点是否存在，不存在创建节点并赋值
        final boolean exists = zkClient.exists("/lg-client");
        if(!exists) {
            zkClient.createEphemeral("/lg-client", 123);
        }
        //注册监听器，节点数据改变的类型，接收通知后的处理逻辑定义
        zkClient.subscribeDataChanges("/lg-client", new IZkDataListener() {
            public void handleDataChange(String path, Object data) throws Exception {
                //定义接收通知之后的处理逻辑
                System.out.println(path +" data is change, new data" + data);
            }
            //数据删除-》节点删除
            public void handleDataDeleted(String path) throws Exception {
                System.out.println(path +" is deleted!!");
            }
        });
        //更新节点夫人数据，删除节点，验证监听器是否正常运行
        final Object o = zkClient.readData("/lg-client");
        System.out.println(o);
        zkClient.writeData("/lg-client", "new data");
        Thread.sleep(1000);
        //删除节点
        zkClient.delete("/lg-client");
        Thread.sleep(Integer.MAX_VALUE);
    }
}

package com.lagou.zk.demo;

import org.I0Itec.zkclient.exception.ZkMarshallingError;
import org.I0Itec.zkclient.serialize.ZkSerializer;

public class ZkStrSerializer implements ZkSerializer {
    //序列化，数据-->byte[]
    public byte[] serialize(Object o) throws ZkMarshallingError {
        return String.valueOf(o).getBytes();
    }
    //反序列化，byte[]-->数据
    public Object deserialize(byte[] bytes) throws ZkMarshallingError {
        return new String(bytes);
    }
}

	运行结果：
	          123
               /lg-client data is change, new datanew data
               /lg-client is deleted!!
	结果表明可以成功监听节点数据变化或删除事件。